
/*
aoeue
 uoueoa */   #include "SourceFileReader.h"  /*  aeuoau
aoeueo
 *  */

#if 1

#include <iostream>
#include <fstream>

#else

#include <iostream>  /*
this doesn't compile for me but the same, but the same done to other headers works;p
*/ #include <fstream>

#endif

/*  aaaa*/  #include /* aaa */ "boost/regex.hpp"   /* aaa */

#include "Util.h"



using namespace analyzer;

SourceFileReader::SourceFileReader(void)
{
	// empty constructor
}


SourceFileReader::~SourceFileReader(void)
{
	// empty descrtuctor
}

std::vector<std::string> SourceFileReader::readFileImports(const FileInfo& fileInfo) {

	std::vector<std::string> imports;
	std::string line;
	
	boost::regex reg("\\s*#include\\s*[\"]([a-zA-Z1-9_.-\\/]+)[\"]\\s*");
	boost::smatch match;
	
	std::ifstream input(fileInfo.getPath().c_str(), std::ios_base::in);
	
	if (!input.is_open()) {
		log(ERROR, boost::format("Couldn't read header file: %1%.") % fileInfo.getPath());
	}
	
	bool multi_line_comment = false;
	while(getline(input, line)) {
		#if 0 // this doesn't catch all cases
		if (multi_line_comment) { // multiline comment started in previous lines
			size_t end_pos = line.find("*/");
			if (end_pos == std::string::npos) // no ending */ so ignore whole line
				continue;
			line.erase (0, end_pos + 2); // end of comment so remove and interpret rest of the line
			multi_line_comment = false;
		}
		// if we reach this we're not in a multiline comment
		size_t pos = line.find("//");
		if (pos != std::string::npos)
			line.erase (pos); // delete so we don't catch any: // /*
		
		while (1) {// there can be many short /* aoeu */ sequences in a line
			size_t beg_pos = line.find("/*");
			if (beg_pos == std::string::npos)
				break;
			
			size_t end_pos = line.find("*/", beg_pos+2); // begin after /* to not catch /*/ as if it was /**/
			if (end_pos == std::string::npos) { // no ending */
				multi_line_comment = true; // so start of multiline comment
				line.erase (beg_pos);
				// don't "continue;" so we still parse in case: #include "a.h" /*
			}else {
			//	std::cout << "line b !" << line << "!\n";
				line.erase (beg_pos, end_pos - beg_pos + 2);
			//	std::cout << "line a !" << line << "!\n";
			}
		}
		#else // this is correct
		if (multi_line_comment) { // multiline comment started in previous lines
			size_t end_pos = line.find("*/");
			if (end_pos == std::string::npos) // no ending */ so ignore whole line
				continue;
			line.erase (0, end_pos + 2); // end of comment so remove and interpret rest of the line
			multi_line_comment = false;
		}
		size_t state = 0;
		for (int i = 0; line.length() && i < line.length()-1; i++) { // scan one character at a time, one less than length because we check the next character
			if (line.at(i) == '/') {
				if (line.at(i+1) == '/') {// one line comment remove rest of line
					line.erase (i);
					break;
				}else if (line.at(i+1) == '*') { //block comment
					for (size_t j = i+2; ; j++) { // search for ending */ in this line
						if (j >= line.length()-1) { // not found
							line.erase(i); // so remove
							multi_line_comment = true; // start multiline comment
							goto break2; //break out of both loops and interpret the line in case of #include "whatever"  /* comment
						}
						if (line.at(j) == '*' && line.at(j+1) == '/') { //found */
							line.erase(i, j-i+2); // so remove and continue the main loop in case of more comments
							i--; // necessary since we'll do i++; and that would skip one character right after /*  */
							break;
						}
					}
				}
			}
		}
		break2: //break out of both loops
		#endif
		
		log(DEBUG, "SourceFileReader", "readFileImports", boost::format("Parsing includes in line '%1%'") % (line));
		
		// all comments are now removed
		// checks if the line contains just the include directive surrounded by whitespaces
		if(boost::regex_match(line, match, reg)) {
			size_t start = match[0].first - line.begin();
			
			// makes sure that the groups has been matched
			if(match[1].matched) {
				// adds the name of included file to the imports
				log(DEBUG, "SourceFileReader", "readFileImports", boost::format("Pushing '%1%'") % (match[1].str()));
				imports.push_back(match[1].str());
			}
		}
	}
	
	// closes the file
	input.close();
	
	// returns the result
	return imports;
}
